package com.time.workbench.efficient.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.time.workbench.core.entity.base.Result;
import com.time.workbench.efficient.entity.vo.GitCommitVO;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class GitlabUtil extends GItAbstractUtil {
    /**
     * 分支
     */
    private final String branches = "/api/v4/projects/{}/repository/branches";
    /**
     * commits
     */
    private final String commits = "/api/v4/projects/{}/repository/commits";
    /**
     * mergeRequest
     */
    private final String mergeRequests = "/api/v4/projects/{}/merge_requests";

    /**
     * merge
     */
    private final String merge = "/api/v4/projects/{}/merge_requests/{}/merge";


    @Override
    public List<String> branchAll() {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("per_page", 100);
        String result = getMethodGit(StrUtil.format(branches, projectEncoding()), paramMap);
        JSONArray array = JSONArray.parseArray(result);
        return array.stream().map(item -> {
            JSONObject itemObj = (JSONObject) item;
            return itemObj.getString("name");
        }).collect(Collectors.toList());
    }

    @Override
    public List<GitCommitVO> commitAll(String branch) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("ref_name", branch);
        String result = getMethodGit(StrUtil.format(commits, projectEncoding()), paramMap);
        JSONArray array = JSONArray.parseArray(result);
        return array.stream().map(item -> {
            JSONObject commit = (JSONObject) item;
            GitCommitVO gitCommitVO = new GitCommitVO();
            gitCommitVO.setCommitId(commit.getString("id"));
            gitCommitVO.setCommitMessage(commit.getString("title"));
            gitCommitVO.setAuthorName(commit.getString("committer_name"));
            gitCommitVO.setDate(commit.getString("committed_date"));
            gitCommitVO.setEmail(commit.getString("committer_email"));
            gitCommitVO.setHtmlUrl(commit.getString("web_url"));
            return gitCommitVO;
        }).collect(Collectors.toList());
    }

    @Override
    public Result<String> createBranch(String oldBranch, String newBranch) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("branch", newBranch);
        paramMap.put("ref", oldBranch);
        String result = postMethodGit(StrUtil.format(branches, projectEncoding()), paramMap);
        JSONObject resultObject = JSON.parseObject(result);
        String resultBranchName = resultObject.getString("name");
        if (StrUtil.isEmpty(resultBranchName)) {
            return Result.fail(resultObject.getString("message"));
        }
        return Result.success("", resultBranchName);
    }

    @Override
    public Result<Integer> createPR(String title, String sourceBranch, String targetBranch, boolean isDeleteSource) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("source_branch", sourceBranch);
        paramMap.put("target_branch", targetBranch);
        paramMap.put("title", title);
        paramMap.put("remove_source_branch", isDeleteSource);
        String result = postMethodGit(StrUtil.format(mergeRequests, projectEncoding()), paramMap);
        JSONObject resultObject = JSON.parseObject(result);
        Integer number = resultObject.getInteger("iid");
        if (number == null) {
            return Result.fail(resultObject.getString("message"));
        }
        return Result.success("", number);
    }

    @Override
    public Result<String> review(Integer number) {
        return null;
    }

    @Override
    public Result<String> test(Integer number) {
        return null;
    }

    @Override
    public Result<String> merge(Integer number, boolean isDeleteSource) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("should_remove_source_branch", isDeleteSource);
        String result = putMethodGit(StrUtil.format(merge, projectEncoding(), number), paramMap);
        JSONObject resultObject = JSON.parseObject(result);
        Integer id = resultObject.getInteger("id");
        if (id == null) {
            return Result.fail(resultObject.getString("message"));
        }
        return Result.success("", id);
    }

    @Override
    public void closeMergeRequest(Integer number) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("state_event", "close");
        putMethodGit(StrUtil.format(mergeRequests + "/{}", projectEncoding(), number), paramMap);
    }

    private String postMethodGit(String uri, HashMap<String, Object> paramMap) {
        if (paramMap == null) paramMap = new HashMap<>();
        log.info("gitlab method:post url:{} 请求:{}", gitConfig.getGitLabUrl() + uri, JSON.toJSONString(paramMap));
        String body = HttpRequest.post(gitConfig.getGitLabUrl() + uri).header("PRIVATE-TOKEN", gitConfig.getGitLabToken()).timeout(-1).body(JSON.toJSONString(paramMap)).execute().body();
        log.info("gitlab method:post url:{} 响应:{}", gitConfig.getGitLabUrl() + uri, body);
        return body;
    }

    private String putMethodGit(String uri, HashMap<String, Object> paramMap) {
        if (paramMap == null) paramMap = new HashMap<>();
        log.info("gitlab method:put url:{} 请求:{}", gitConfig.getGitLabUrl() + uri, JSON.toJSONString(paramMap));
        String body = HttpRequest.put(gitConfig.getGitLabUrl() + uri).header("PRIVATE-TOKEN", gitConfig.getGitLabToken()).timeout(-1).body(JSON.toJSONString(paramMap)).execute().body();
        log.info("gitlab method:put url:{} 响应:{}", gitConfig.getGitLabUrl() + uri, body);
        return body;
    }


    private String getMethodGit(String uri, HashMap<String, Object> paramMap) {
        if (paramMap == null) paramMap = new HashMap<>();
        log.info("gitlab method:get url:{} 请求:{}", gitConfig.getGitLabUrl() + uri, JSON.toJSONString(paramMap));
        String body = HttpRequest.get(gitConfig.getGitLabUrl() + uri).header("PRIVATE-TOKEN", gitConfig.getGitLabToken()).form(paramMap).execute().body();
        log.info("gitlab method:get url:{} 响应:{}", gitConfig.getGitLabUrl() + uri, body);
        return body;
    }

    private String deleteMethodGit(String uri, HashMap<String, Object> paramMap) {
        if (paramMap == null) paramMap = new HashMap<>();
        log.info("gitlab method:delete url:{} 请求:{}", gitConfig.getGitLabUrl() + uri, JSON.toJSONString(paramMap));
        String body = HttpRequest.delete(gitConfig.getGitLabUrl() + uri).header("PRIVATE-TOKEN", gitConfig.getGitLabToken()).form(paramMap).execute().body();
        log.info("gitlab method:delete url:{} 响应:{}", gitConfig.getGitLabUrl() + uri, body);
        return body;
    }

    private String projectEncoding() {
        List<String> ownerRepo = getUriArray();
        String projectUri = CollectionUtil.join(ownerRepo, "/");
        if (projectUri.startsWith("/")) {
            projectUri = projectUri.substring(1);
        }
        return URLUtil.encodeAll(projectUri);
    }
}
